"""
封装的HTTP请求客户端
"""
import requests
import httpx
import time
import asyncio
from typing import Dict, Any, Optional
from config.settings import settings
import logging

logger = logging.getLogger(__name__)


class APIClient:
    """HTTP API客户端"""
    
    def __init__(self, base_url: str = None, timeout: int = None):
        self.base_url = base_url or settings.get("api.base_url", "")
        self.timeout = timeout or settings.get("api.timeout", 30)
        self.retry_times = settings.get("api.retry_times", 3)
        
        # 创建会话
        self.session = requests.Session()
        self.async_client = httpx.AsyncClient(timeout=self.timeout)
        
        # 设置默认请求头
        self.session.headers.update({
            "Content-Type": "application/json",
            "User-Agent": "Python-API-Client/1.0"
        })
    
    def _make_request(self, method: str, endpoint: str, **kwargs) -> requests.Response:
        """执行HTTP请求"""
        url = f"{self.base_url}/{endpoint.lstrip('/')}"
        
        for attempt in range(self.retry_times):
            try:
                response = self.session.request(method, url, timeout=self.timeout, **kwargs)
                response.raise_for_status()
                return response
                
            except requests.exceptions.RequestException as e:
                logger.warning(f"请求失败 (尝试 {attempt + 1}/{self.retry_times}): {e}")
                
                if attempt == self.retry_times - 1:
                    raise
                
                # 指数退避
                time.sleep(2 ** attempt)
    
    async def _make_async_request(self, method: str, endpoint: str, **kwargs) -> httpx.Response:
        """执行异步HTTP请求"""
        url = f"{self.base_url}/{endpoint.lstrip('/')}"
        
        for attempt in range(self.retry_times):
            try:
                response = await self.async_client.request(method, url, **kwargs)
                response.raise_for_status()
                return response
                
            except httpx.RequestError as e:
                logger.warning(f"异步请求失败 (尝试 {attempt + 1}/{self.retry_times}): {e}")
                
                if attempt == self.retry_times - 1:
                    raise
                
                # 指数退避
                await asyncio.sleep(2 ** attempt)
    
    def get(self, endpoint: str, params: Optional[Dict] = None, **kwargs) -> Dict[str, Any]:
        """GET请求"""
        response = self._make_request("GET", endpoint, params=params, **kwargs)
        return response.json()
    
    def post(self, endpoint: str, data: Optional[Dict] = None, **kwargs) -> Dict[str, Any]:
        """POST请求"""
        response = self._make_request("POST", endpoint, json=data, **kwargs)
        return response.json()
    
    def put(self, endpoint: str, data: Optional[Dict] = None, **kwargs) -> Dict[str, Any]:
        """PUT请求"""
        response = self._make_request("PUT", endpoint, json=data, **kwargs)
        return response.json()
    
    def delete(self, endpoint: str, **kwargs) -> Dict[str, Any]:
        """DELETE请求"""
        response = self._make_request("DELETE", endpoint, **kwargs)
        return response.json()
    
    async def async_get(self, endpoint: str, params: Optional[Dict] = None, **kwargs) -> Dict[str, Any]:
        """异步GET请求"""
        response = await self._make_async_request("GET", endpoint, params=params, **kwargs)
        return response.json()
    
    async def async_post(self, endpoint: str, data: Optional[Dict] = None, **kwargs) -> Dict[str, Any]:
        """异步POST请求"""
        response = await self._make_async_request("POST", endpoint, json=data, **kwargs)
        return response.json()
    
    def close(self):
        """关闭连接"""
        self.session.close()
    
    async def aclose(self):
        """异步关闭连接"""
        await self.async_client.aclose()


# 全局API客户端实例
api_client = APIClient()